﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HiUpdateTools.Client.Win;
using HiUpdateTools.Core;
using Ionic.Zip;

namespace HiUpdateTools.Client.Wpf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        public UpdateChecker Checker { get; set; }
        public void RunOnUiThread(System.Action action)
        {


            this.Dispatcher.Invoke(action);



        }
        void Copy(string sourceDir, string targetDir)
        {

            if (!Directory.Exists(targetDir))
                Directory.CreateDirectory(targetDir);
            ///Remove old tmp file 
            Directory.GetFiles(targetDir, "*.tmp").ToList().ForEach(file => File.Delete(file));
            Directory.GetFiles(targetDir, "*.PendingOverwrite").ToList().ForEach(file => File.Delete(file));


            foreach (var file in Directory.GetFiles(sourceDir))
            {
                if (file.IndexOf(".deploy") > -1)
                {
                    using (ZipFile zip = ZipFile.Read(file))
                    {
                        zip.ExtractAll(targetDir, ExtractExistingFileAction.OverwriteSilently);
                    }



                }
                else
                    File.Copy(file, System.IO.Path.Combine(targetDir, System.IO.Path.GetFileName(file)), true);
            }
            foreach (var directory in Directory.GetDirectories(sourceDir))
                Copy(directory, System.IO.Path.Combine(targetDir, System.IO.Path.GetFileName(directory)));
        }

        private void Window_Initialized(object sender, EventArgs e)
        {
            if (!App.AppMutex.WaitOne(0, false))
            {
                Application.Current.Shutdown();
                return;
            }

            Checker = new UpdateChecker(App.Args[0], new Version(App.Args[1]));
            Checker.Check();

            lbAplicationName.Content = Checker.ServerConfg.Name;
            lbVersion.Content = Checker.ServerConfg.Version;


            if (Checker != null)
            {
                if (Checker.ClientConfg.AutoUpdate)
                {

                    biUpdate_Click(sender, null);

                }

            }

        }

        private void biUpdate_Click(object sender, RoutedEventArgs e)
        {

            if (!Checker.IsProcessOpen(Checker.ServerConfg.Name))
            {
                biUpdate.Visibility = System.Windows.Visibility.Hidden;

                btSkip.Visibility = System.Windows.Visibility.Hidden;
                lbStatus.Visibility = System.Windows.Visibility.Visible;

                pbStatus.Visibility = System.Windows.Visibility.Visible;
                pbTotal.Visibility = System.Windows.Visibility.Visible;
                string RootPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
                string VersionPath = RootPath + "\\" + Checker.ServerConfg.Version + "\\";
                if (Directory.Exists(VersionPath))
                    Directory.Delete(VersionPath, true);
                Directory.CreateDirectory(VersionPath);
                ///if()
                Checker.Downloader.DownloadProgressChanged += Downloader_DownloadProgressChanged;
                Checker.Downloader.DownloadFileCompleted += Downloader_DownloadFileCompleted;
                pbTotal.Maximum = Checker.ServerConfg.Files.Count;

                ThreadPool.QueueUserWorkItem(a =>
                {
                    Thread.Sleep(2000);
                    try
                    {
                        foreach (ServerConfigFile file in Checker.ServerConfg.Files)
                        {
                            RunOnUiThread(() =>
                             {
                                 lbStatus.Content = string.Format("Downloading {0} - {1}Kb", file.Name, file.Size / 1000);
                                 pbTotal.Value++;

                             });

                            if (file.Name == "\\HiUpdateTools.Client.Win.exe" || file.Name == "\\Ionic.Zip.Reduced.dll" || file.Name == "\\edtFTPnet.dll")
                            {
                                continue;
                            }
                            Uri fileUri = new Uri(String.Format("{0}://{1}/{2}{3}.deploy", Checker.ClientConfg.ClientPathType, Checker.ClientConfg.ClientPath.TrimEnd("/".ToCharArray()), Checker.ServerConfg.Version, file.Name.Replace("\\", "/")));
                            string localFilePath = RootPath + file.Name;
                            if (File.Exists(localFilePath))
                            {
                                FileInfo info = new FileInfo(localFilePath);
                                if (info.Length == file.Size && info.LastWriteTimeUtc == file.Date)
                                {
                                    // Thread.Sleep(5);
                                    continue;
                                }
                            }

                            if (file.Name.LastIndexOf("\\") != 0)
                                Directory.CreateDirectory(VersionPath + file.Name.Substring(0, file.Name.LastIndexOf("\\") + 1));
                            IsBusy = true;
                            Checker.Downloader.DownloadFileAsync(fileUri, VersionPath + file.Name + ".deploy");
                            while (IsBusy)
                                Thread.Sleep(25);

                        }

                        RunOnUiThread(() =>
                             {
                                 lbStatus.Content = string.Format("Prepare run application...");

                                 pbTotal.Visibility = System.Windows.Visibility.Hidden;
                             });
                        Copy(VersionPath, RootPath);
                        Directory.Delete(VersionPath, true);
                        // lbStatus.Text = "Updatuji aplikaci";
                        RunOnUiThread(() =>
                             {
                                 lbStatus.Content = string.Format("Runnnig application...");

                             });

                    }
                    catch (Exception ex)
                    {
                        RunOnUiThread(() =>
                    {
                        ErrorWindow dialog = new ErrorWindow();

                        dialog.Error = ex;
                        dialog.ShowDialog();



                    });
                    }
                    finally
                    {
                        RunOnUiThread(() =>
                            {
                                App.AppMutex.ReleaseMutex();
                                Checker.RunApplication();
                                Application.Current.Shutdown();
                            });

                    }

                });
            }
            else
            {
                App.AppMutex.ReleaseMutex();
                Checker.RunApplication();
                Application.Current.Shutdown();

            }
        }

        void Downloader_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            IsBusy = false;
        }

        void Downloader_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
        {
            RunOnUiThread(() =>
                      {
                          pbStatus.Value = e.ProgressPercentage;
                      });
        }

        private void btSkip_Click(object sender, RoutedEventArgs e)
        {
            Checker.RunApplication();
            Application.Current.Shutdown();
        }


        public bool IsBusy { get; set; }
    }
}
